<template>
  <view
    :class="iconClass"
    :style="iconStyle"
    @click="handleClick"
  >
    <!-- Unicode 图标 -->
    <text v-if="unicode" :style="textStyle">{{ unicode }}</text>

    <!-- UnoCSS 图标 -->
    <text v-else-if="name" :class="iconClass"></text>

    <!-- Image 图标 -->
    <image
      v-else-if="imageSrc"
      :src="imageSrc"
      :class="imageClass"
      :mode="imageMode"
    />

    <!-- 插槽图标 -->
    <slot v-else></slot>
  </view>
</template>

<script setup lang="ts">
import { computed } from 'vue'

interface Props {
  // UnoCSS 图标名称
  name?: string
  // Unicode 图标
  unicode?: string
  // 图片图标地址
  imageSrc?: string
  // 图片裁剪模式
  imageMode?: 'scaleToFill' | 'aspectFit' | 'aspectFill' | 'widthFix' | 'heightFix'
  // 图标尺寸
  size?: number | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
  // 图标颜色
  color?: string
  // 是否可点击
  clickable?: boolean
  // 自定义类名
  customClass?: string
}

const props = withDefaults(defineProps<Props>(), {
  name: '',
  unicode: '',
  imageSrc: '',
  imageMode: 'aspectFit',
  size: 'md',
  color: '',
  clickable: false,
  customClass: '',
})

const emit = defineEmits<{
  click: [event: Event]
}>()

// 图标尺寸映射
const sizeMap = {
  xs: 12,
  sm: 16,
  md: 20,
  lg: 24,
  xl: 32,
}

// 计算尺寸
const sizeValue = computed(() => {
  if (typeof props.size === 'number') {
    return props.size
  }
  return sizeMap[props.size]
})

// 图标样式
const iconClass = computed(() => {
  const baseClass = 'inline-flex items-center justify-center transition-colors'

  const sizeClass = typeof props.size === 'number' ? '' : `icon-${props.size}`

  const interactiveClass = props.clickable
    ? 'cursor-pointer hover:opacity-80 active:scale-95'
    : ''

  const iconClass = props.name ? `i-${props.name}` : ''

  return [
    baseClass,
    sizeClass,
    interactiveClass,
    iconClass,
    props.customClass,
  ].filter(Boolean).join(' ')
})

// 图标内联样式
const iconStyle = computed(() => {
  const size = typeof props.size === 'number' ? `${sizeValue.value}rpx` : ''
  const color = props.color || 'var(--text-primary)'

  return {
    width: size,
    height: size,
    fontSize: size,
    color,
  }
})

// Unicode 文字样式
const textStyle = computed(() => {
  return {
    fontSize: iconStyle.value.fontSize,
    color: iconStyle.value.color,
  }
})

// 图片样式
const imageClass = computed(() => {
  return [
    'w-full h-full',
  ].join(' ')
})

const handleClick = (event: Event) => {
  if (props.clickable) {
    emit('click', event)
  }
}
</script>

<style scoped>
.icon-xs {
  width: 24rpx;
  height: 24rpx;
  font-size: 24rpx;
}

.icon-sm {
  width: 32rpx;
  height: 32rpx;
  font-size: 32rpx;
}

.icon-md {
  width: 40rpx;
  height: 40rpx;
  font-size: 40rpx;
}

.icon-lg {
  width: 48rpx;
  height: 48rpx;
  font-size: 48rpx;
}

.icon-xl {
  width: 64rpx;
  height: 64rpx;
  font-size: 64rpx;
}

.active\:scale-95:active {
  transform: scale(0.95);
}
</style>